package cn.edu.tju.wallet.domain;

import cn.edu.tju.core.model.BaseEntity;
import jakarta.persistence.*;
import java.math.BigDecimal;

/**
 * 交易流水实体（充血模型）
 * 包含交易数据和交易相关的业务逻辑
 */
@Entity
@Table(name = "transactions")
public class Transaction extends BaseEntity {

    @Column(name = "wallet_id", nullable = false)
    private Long walletId; // 钱包ID

    @Enumerated(EnumType.STRING)
    @Column(name = "transaction_type", nullable = false, length = 50)
    private TransactionType type; // 交易类型

    @Column(name = "amount", precision = 19, scale = 2, nullable = false)
    private BigDecimal amount; // 交易金额

    @Column(name = "balance_before", precision = 19, scale = 2, nullable = false)
    private BigDecimal balanceBefore; // 交易前余额

    @Column(name = "balance_after", precision = 19, scale = 2, nullable = false)
    private BigDecimal balanceAfter; // 交易后余额

    @Enumerated(EnumType.STRING)
    @Column(name = "status", nullable = false, length = 20)
    private TransactionStatus status = TransactionStatus.SUCCESS; // 交易状态

    @Column(name = "related_transaction_id")
    private Long relatedTransactionId; // 相关交易ID

    @Column(name = "order_id")
    private Long orderId; // 订单ID

    @Column(name = "remark", length = 500)
    private String remark; // 备注

    // ============================================
    // 构造函数
    // ============================================

    public Transaction() {
        setDeleted(false); // 初始化is_deleted字段，默认为false
    }

    public Transaction(Long walletId, TransactionType type, BigDecimal amount,
                      BigDecimal balanceBefore, BigDecimal balanceAfter) {
        this.walletId = walletId;
        this.type = type;
        this.amount = amount;
        this.balanceBefore = balanceBefore;
        this.balanceAfter = balanceAfter;
        this.status = TransactionStatus.SUCCESS;
        setDeleted(false); // 初始化is_deleted字段，默认为false
    }

    // ============================================
    // 核心业务方法
    // ============================================

    /**
     * 判断是否为收入交易（充值、收款、解冻等）
     * @return 是否为收入交易
     */
    public boolean isIncome() {
        return type == TransactionType.RECHARGE ||
               type == TransactionType.RECEIPT ||
               type == TransactionType.UNFREEZE ||
               type == TransactionType.REFUND ||
               amount.compareTo(BigDecimal.ZERO) > 0;
    }

    /**
     * 判断是否为支出交易（提现、支付、冻结等）
     * @return 是否为支出交易
     */
    public boolean isExpense() {
        return type == TransactionType.WITHDRAW ||
               type == TransactionType.PAYMENT ||
               type == TransactionType.FREEZE ||
               type == TransactionType.OVERDRAFT ||
               amount.compareTo(BigDecimal.ZERO) < 0;
    }

    /**
     * 判断交易是否成功
     * @return 交易是否成功
     */
    public boolean isSuccessful() {
        return status == TransactionStatus.SUCCESS;
    }

    /**
     * 判断交易是否失败
     * @return 交易是否失败
     */
    public boolean isFailed() {
        return status == TransactionStatus.FAILED;
    }

    /**
     * 判断交易是否待处理
     * @return 交易是否待处理
     */
    public boolean isPending() {
        return status == TransactionStatus.PENDING;
    }

    /**
     * 判断交易是否已取消
     * @return 交易是否已取消
     */
    public boolean isCancelled() {
        return status == TransactionStatus.CANCELLED;
    }

    /**
     * 获取交易金额的绝对值
     * @return 交易金额的绝对值
     */
    public BigDecimal getAbsoluteAmount() {
        return amount.abs();
    }

    /**
     * 计算余额变动
     * @return 余额变动（正数表示增加，负数表示减少）
     */
    public BigDecimal getBalanceChange() {
        return balanceAfter.subtract(balanceBefore);
    }

    /**
     * 验证交易数据的完整性
     * @throws IllegalStateException 当交易数据不完整时
     */
    public void validate() {
        if (walletId == null) {
            throw new IllegalStateException("钱包ID不能为空");
        }
        if (type == null) {
            throw new IllegalStateException("交易类型不能为空");
        }
        if (amount == null) {
            throw new IllegalStateException("交易金额不能为空");
        }
        if (balanceBefore == null || balanceAfter == null) {
            throw new IllegalStateException("余额信息不能为空");
        }
        if (status == null) {
            throw new IllegalStateException("交易状态不能为空");
        }
    }

    /**
     * 标记交易为成功状态
     * @return 当前的交易对象
     */
    public Transaction markAsSuccessful() {
        this.status = TransactionStatus.SUCCESS;
        return this;
    }

    /**
     * 标记交易为失败状态
     * @param reason 失败原因
     * @return 当前的交易对象
     */
    public Transaction markAsFailed(String reason) {
        this.status = TransactionStatus.FAILED;
        if (reason != null && !reason.trim().isEmpty()) {
            this.remark = (this.remark != null ? this.remark + "; " : "") + "失败原因: " + reason;
        }
        return this;
    }

    /**
     * 标记交易为待处理状态
     * @return 当前的交易对象
     */
    public Transaction markAsPending() {
        this.status = TransactionStatus.PENDING;
        return this;
    }

    /**
     * 标记交易为已取消状态
     * @param reason 取消原因
     * @return 当前的交易对象
     */
    public Transaction cancel(String reason) {
        this.status = TransactionStatus.CANCELLED;
        if (reason != null && !reason.trim().isEmpty()) {
            this.remark = (this.remark != null ? this.remark + "; " : "") + "取消原因: " + reason;
        }
        return this;
    }

    /**
     * 设置相关交易ID
     * @param relatedTransactionId 相关交易ID
     * @return 当前的交易对象
     */
    public Transaction linkTo(Long relatedTransactionId) {
        this.relatedTransactionId = relatedTransactionId;
        return this;
    }

    /**
     * 设置订单ID
     * @param orderId 订单ID
     * @return 当前的交易对象
     */
    public Transaction forOrder(Long orderId) {
        this.orderId = orderId;
        return this;
    }

    /**
     * 设置备注
     * @param remark 备注
     * @return 当前的交易对象
     */
    public Transaction withRemark(String remark) {
        this.remark = remark;
        return this;
    }

    /**
     * 获取交易描述
     * @return 交易描述
     */
    public String getDescription() {
        String typeDesc = getTypeDescription();
        String amountStr = String.format("%.2f元", amount.abs());
        String statusDesc = getStatusDescription();
        return String.format("%s %s %s", typeDesc, amountStr, statusDesc);
    }

    /**
     * 获取交易类型的中文描述
     * @return 交易类型描述
     */
    public String getTypeDescription() {
        switch (type) {
            case RECHARGE: return "充值";
            case WITHDRAW: return "提现";
            case PAYMENT: return "支付";
            case RECEIPT: return "收款";
            case FREEZE: return "冻结";
            case UNFREEZE: return "解冻";
            case OVERDRAFT: return "透支";
            case REPAY: return "还款";
            case REFUND: return "退款";
            default: return "未知交易";
        }
    }

    /**
     * 获取交易状态的中文描述
     * @return 交易状态描述
     */
    public String getStatusDescription() {
        switch (status) {
            case PENDING: return "（待处理）";
            case SUCCESS: return "（成功）";
            case FAILED: return "（失败）";
            case CANCELLED: return "（已取消）";
            default: return "（未知状态）";
        }
    }

    // 交易类型
    public enum TransactionType {
        RECHARGE,   // 充值
        WITHDRAW,   // 提现
        PAYMENT,    // 支付
        RECEIPT,    // 收款
        FREEZE,     // 冻结
        UNFREEZE,   // 解冻
        OVERDRAFT,  // 透支
        REPAY,      // 还款
        REFUND      // 退款
    }

    // 交易状态
    public enum TransactionStatus {
        PENDING,    // 待处理
        SUCCESS,    // 成功
        FAILED,     // 失败
        CANCELLED   // 已取消
    }

    // ============================================
    // Getter and Setter
    // ============================================

    public Long getWalletId() {
        return walletId;
    }

    public void setWalletId(Long walletId) {
        this.walletId = walletId;
    }

    public TransactionType getType() {
        return type;
    }

    public void setType(TransactionType type) {
        this.type = type;
    }

    public BigDecimal getAmount() {
        return amount;
    }

    public void setAmount(BigDecimal amount) {
        this.amount = amount;
    }

    public BigDecimal getBalanceBefore() {
        return balanceBefore;
    }

    public void setBalanceBefore(BigDecimal balanceBefore) {
        this.balanceBefore = balanceBefore;
    }

    public BigDecimal getBalanceAfter() {
        return balanceAfter;
    }

    public void setBalanceAfter(BigDecimal balanceAfter) {
        this.balanceAfter = balanceAfter;
    }

    public TransactionStatus getStatus() {
        return status;
    }

    public void setStatus(TransactionStatus status) {
        this.status = status;
    }

    public Long getRelatedTransactionId() {
        return relatedTransactionId;
    }

    public void setRelatedTransactionId(Long relatedTransactionId) {
        this.relatedTransactionId = relatedTransactionId;
    }

    public Long getOrderId() {
        return orderId;
    }

    public void setOrderId(Long orderId) {
        this.orderId = orderId;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }
}

